
package com.yuke.cloud.service.uac.controller.frontend;

import com.google.common.base.Preconditions;
import com.yuke.cloud.common.base.constant.GlobalConstant;
import com.yuke.cloud.common.core.annotation.NoRepeatSubmit;
import com.yuke.cloud.common.core.aspect.NoRepeatSubmitAop;
import com.yuke.cloud.common.core.support.BaseController;
import com.yuke.cloud.common.core.utils.RequestUtil;
import com.yuke.cloud.common.util.PublicUtil;
import com.yuke.cloud.common.util.wrapper.WrapMapper;
import com.yuke.cloud.common.util.wrapper.Wrapper;
import com.yuke.cloud.service.uac.dto.LoginRespDto;
import com.yuke.cloud.service.uac.service.AccLoginService;
import com.yuke.cloud.service.uac.service.AccUserTokenService;
import com.yuke.cloud.service.uac.utils.Md5Util;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;


/**
 * 登录相关.
 *
 * @author
 */
@Slf4j
@RestController
@RequestMapping(value = "", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@Api(value = "Web - UacUserLoginController", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ComponentScan(basePackageClasses={NoRepeatSubmitAop.class})
public class AccUserLoginController extends BaseController {

	@Resource
	private AccLoginService accLoginService;
	@Resource
	private AccUserTokenService accUserTokenService;
	@Resource
	private ClientDetailsService clientDetailsService;
	private static final String BEARER_TOKEN_TYPE = "Basic ";


	/**
	 * 登录页面请求
	 */
	@GetMapping("/auth/require")
	public Wrapper requireAuthentication() {
		return WrapMapper.wrap(HttpStatus.UNAUTHORIZED.value(), "访问的服务器需要身份认证，先登录认证");
	}


		/**
         * 登录成功获取菜单信息和用户信息.
         *
         *
         * @return the wrapper
         */
	@GetMapping(value = "/user/loginAfter")
	@ApiOperation(httpMethod = "GET", value = "登录成功获取用户相关信息")
	public Wrapper<LoginRespDto> loginAfter() {
		LoginRespDto result = accLoginService.loginAfter(GlobalConstant.Sys.OPER_APPLICATION_ID);
		return WrapMapper.ok(result);
	}

	/**
	 * 登出.
	 *
	 * @param request the HttpServletRequest
	 *
	 * @return the wrapper
	 */
	@PostMapping(value = "/user/logout")
	@ApiOperation(httpMethod = "POST", value = "登出")
	public Wrapper loginOut(HttpServletRequest request) {
		//mod by wg 20181230 增加异常处理,如果头中带bearer等处理
//		String accessToken = StringUtils.substringAfter(request.getHeader(HttpHeaders.AUTHORIZATION), "Bearer ");
		String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
		String authPrefix = "Bearer ";
		String accessToken = "";
		if (PublicUtil.isNotEmpty(authHeader) && StringUtils.startsWithIgnoreCase(authHeader, authPrefix)) {
			accessToken = StringUtils.substring(authHeader, authPrefix.length());
		}
//		logger.info(accessToken);
		if (!StringUtils.isEmpty(accessToken)) {
//			// 修改用户在线状态
			//mod by wg 20181220 如果是登出，直接删除
//			UserTokenDto userTokenDto = accUserTokenService.getByAccessToken(accessToken);
//			userTokenDto.setStatus(AccUserTokenStatusEnum.OFF_LINE.getStatus());
//			accUserTokenService.updateUacUserToken(userTokenDto, getLoginAuthDto());
			accUserTokenService.deleteUacUserToken(accessToken);
		}
		return WrapMapper.ok();
	}

	/**
	 * 刷新token.
	 *
	 * @param request      the request
	 * @param refreshToken the refresh token
	 * @param accessToken  the access token
	 *
	 * @return the wrapper
	 */
	@GetMapping(value = "/auth/user/refreshToken")
	@ApiOperation(httpMethod = "GET", value = "刷新token")
	@NoRepeatSubmit  // add by wg 20190408 防止重复提交请求
	public Wrapper<String> refreshToken(HttpServletRequest request, @RequestParam(value = "refreshToken") String refreshToken, @RequestParam(value = "accessToken") String accessToken) {
		log.info("刷新token--AccUserLoginController-refreshToken");
		String token;
		try {
			Preconditions.checkArgument(org.apache.commons.lang3.StringUtils.isNotEmpty(accessToken), "accessToken is null");
			Preconditions.checkArgument(org.apache.commons.lang3.StringUtils.isNotEmpty(refreshToken), "refreshToken is null");
			String header = request.getHeader(HttpHeaders.AUTHORIZATION);
//			if (header == null || !header.startsWith(BEARER_TOKEN_TYPE)) {
			if (header == null || !StringUtils.startsWithIgnoreCase(header, BEARER_TOKEN_TYPE)) {
				throw new UnapprovedClientAuthenticationException("请求头中无client信息");
			}
			String[] tokens = RequestUtil.extractAndDecodeHeader(header);
			assert tokens.length == 2;

			String clientId = tokens[0];
			String clientSecret = tokens[1];

			ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);

			if (clientDetails == null) {
				throw new UnapprovedClientAuthenticationException("clientId对应的配置信息不存在:" + clientId);
			} else if (!Md5Util.matches(clientSecret, clientDetails.getClientSecret())) { ////mod by wg 20180918 else if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {
				throw new UnapprovedClientAuthenticationException("clientSecret不匹配:" + clientId);
			}

			token = accUserTokenService.refreshToken(accessToken, refreshToken, request);
		} catch (Exception e) {
			logger.error("refreshToken={}", e.getMessage(), e);
			return WrapMapper.error();
		}
		return WrapMapper.ok(token);
	}

}